import re

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework import serializers
from users.models import UserModel
from django_redis import get_redis_connection


class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token['username'] = str(user.username)
        token['avatar'] = str(user.avatar)
        token['money'] = str(user.money)
        token['credit'] = str(user.credit)
        return token


class RegisterSerializer(serializers.ModelSerializer):
    re_password = serializers.CharField(required=True, write_only=True, min_length=6, max_length=16)
    sms_code = serializers.CharField(required=True, write_only=True, min_length=3, max_length=5)

    # 仅在序列化中使用，用于注册成功后，返回登录令牌 ；toekn  refresh
    token = serializers.CharField(read_only=True)
    refresh = serializers.CharField(read_only=True)

    class Meta:
        model = UserModel
        fields = ['password', 'mobile', 'token', 'refresh', 're_password', 'sms_code']
        extra_kwargs = {
            'mobile': {
                'required': True,
                'write_only': True
            },
            'password': {
                'required': True,
                'write_only': True,
                'min_length': 6,
                'max_length': 16,
            }
        }

    def validate(self, attrs):
        # 自定义任意校验规则
        # 校验传递数据，是否满足业务需求
        mobile = attrs.get('mobile', None)
        # 判断手机号是否满足规则
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            raise serializers.ValidationError(detail="手机号格式错误", code="mobile")
        print('-------手机号校验通过--------')

        # 校验两次密码是否相同
        password = attrs.get('password')
        re_password = attrs.get('re_password')
        if password != re_password:
            raise serializers.ValidationError(detail="两次密码不一致,请重新输入密码", code="password")
        print('-------密码校验通过,两次密码相同---------')

        # 验证码操作 稍后开发
        # 默认验证码是正确
        # -------------------redis:短信验证码------------------
        sms_code = attrs.get('sms_code')
        redis = get_redis_connection('sms_code')
        code = redis.get(f'sms_{mobile}')
        # redis中获取到数据类型,都是字节类型的
        print('redis中保存的短信验证码:', code)
        if code == None:
            raise serializers.ValidationError(detail='验证码过期,请重新获取验证码', code="sms_code")
        elif code.decode() != sms_code:
            raise serializers.ValidationError(detail='验证码错误,请重新输入', code='sms_code')
        else:
            redis.delete(f'sms_{mobile}')

        # 程序健壮性考虑
        # 判断一次用户是否存在
        try:
            UserModel.objects.get(mobile__exact=mobile)
            raise serializers.ValidationError(detail='用户已经存在了...', code='mobile')
        except UserModel.DoesNotExist:
            print('注册信息,不存在于数据,可以正常执行注册操作.所有数据校验通过')
        # 校验通过，删除不必要得字段
        attrs.pop('re_password')
        attrs.pop('sms_code')
        return attrs

    def create(self, validated_data):
        mobile = validated_data.get('mobile')
        password = validated_data.get('password')
        # 注册新用户，初始化用户信息
        user = UserModel.objects.create_user(
            mobile=mobile,
            password=password,
            # 随机给默认用户名 ,根据需求随机生成  小伙子_KFDSKJLK_123
            username=mobile,
            money=0.0,
            credit=0,
            avatar="avatar/2021/default.jpg"
        )

        refresh = CustomTokenObtainPairSerializer.get_token(user)
        user.refresh = str(refresh)
        user.token = str(refresh.access_token)
        return user
